package com.df.ez_game.server.logic;

import com.df.ez_game.server.*;
import com.df.ez_game.server.msg.client.ClientReqMsg;
import com.df.ez_game.server.req_metadata.ControllerMetadatas;
import com.df.ez_game.tools.EzUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

@Slf4j
@Accessors(chain = true)
@Data
public class LogicServerNode extends ServerNode {
    AtomicBoolean started = new AtomicBoolean(false);
    @ToString.Exclude()
    LogicSettings settings = new LogicSettings();
    //broker管理器
    BrokerManager brokerManager;
    //服务
    @ToString.Exclude()
    NettyServer nettyServer;
    //请求元数据
    ControllerMetadatas metadatas = new ControllerMetadatas();

    //消息分发器
    MsgDispatcher<LogicServerNode, ClientReqMsg> dispatcher ;

    //会话管理器{channelid:session}
    ConcurrentHashMap<ChannelId,UserSession> sessions = new ConcurrentHashMap<>();
    //会话管理器{loginId:session}
    ConcurrentHashMap<Long,UserSession> loginSessions = new ConcurrentHashMap<>();
    //广播id和类型的映射
    Map<Integer,PushMsgMeta> pushMsgMap = new HashMap<>();
    //异常code和msg映射
    Map<Integer,String> exceptionMsgMap = new HashMap<>();

    //文档服务器
    DocServer docServer;

    @Override
    public void start() {
        boolean canStart = started.compareAndSet(false, true);
        if(!canStart){
            return;
        }
        if(getName()==null|| getName().trim().equals("")){
            setName("default");
        }
        setType(settings.getNodeType());
        metadatas.setMsgProtoType(settings.getMsgProtoc());
        if(settings.isDebug()){
            settings.getFilters().add(new DebugMsgFilter());
        }
        settings.getStartSuccessCb().add(channel -> {
            ServerManager.register(this);
        });
        if(settings.isDocServer()){
            if(settings.getDocServerPort()==null){
                throw new RuntimeException("文档服的端口未设置！启动失败");
            }
            docServer = new DocServer("doc",settings.getDocServerPort());
            docServer.start();
        }
        if(settings.nodeType==NodeType.SingletonLogic){
            startStandAloneServer();
            return;
        }
        startClussorServer();
    }

    /**
     * 异步起动
     */
    public void startAsync(){

    }

    private void startClussorServer() {


    }

    private void startStandAloneServer(){
        //根据实例收集controller信息
        metadatas.parserControllers(settings.controllerInstance);
        //TODO 根据包名收集
        //收集服务器推送给客户都的信息
        if(!settings.getPushEnumClass().isEmpty()){
            EzUtils.pushEnumsHandle(this.settings.getPushEnumClass(),pushMsgMap);
        }
        //收集服务器业务异常码
        if(!settings.getExceptionClass().isEmpty()){
            EzUtils.exceptionDataHandle(this.settings.exceptionClass,exceptionMsgMap);
        }
        //设置工作队列大小
        if(dispatcher==null){
            dispatcher = new LogicMsgDispatcher(settings);
        }
        //启动netty服务器
        if(nettyServer==null){
            nettyServer = new NettyServer();
            NettyServerSettings serverSettings= null;
            if(settings.getNetProtoc().equals(NetProtocType.TCP.getValue())){
                serverSettings = new StandAloneTcpNettyServerSettings();
            }else if(settings.getNetProtoc().equals(NetProtocType.WEBSOCKET.getValue())){
                StandAloneWebsocketNettyServerSettings wsSetting = new StandAloneWebsocketNettyServerSettings();
                String wsPath = settings.getWsPath();
                if(wsPath==null || wsPath.isEmpty()){
                    wsPath = "/ws";
                    settings.setWsPath("/ws");
                }
                wsSetting.setPath(wsPath);
                serverSettings = wsSetting;
            }else if(settings.getNetProtoc().equals(NetProtocType.UDP.getValue())){

            }

            serverSettings.setServerNode(this);
            serverSettings.setServerPort(settings.getPort());
            nettyServer.setSettings(serverSettings);
        }
        nettyServer.startUp(channel -> {
            //TODO 回调顺序
            for (Consumer<Channel> consumer : settings.getStartSuccessCb()) {
                consumer.accept(channel);
            }
        },channel -> {
            //TODO 回调顺序
            for (Consumer<Channel> consumer : settings.getStartFailCb()) {
                consumer.accept(channel);
            }
        });
    }




    @Override
    public void stop() {

    }

    @Override
    public void registerToBrokerManager() {

    }

    @Override
    public void sendHeartbeat() {

    }

    @Override
    public void shutDown() {
        if(nettyServer!=null){
            nettyServer.shutDown();
        }
        ServerManager.unRegister(this.getName());
        System.out.println("服务关闭："+getName());
    }

    //连接broker的connector
//    private
}
